/*
 * Copyright (C) 2012 Martin Řehánek <rehan at mzk.cz>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package cz.mzk.kramerius.k4audiopoc.urlMapping;

import cz.mzk.kramerius.commons.DatastreamId;
import cz.mzk.kramerius.commons.Dom4jUtils;
import cz.mzk.kramerius.fedoraaccess.FedoraConnector;
import cz.mzk.kramerius.fedoraaccess.FedoraServer;
import cz.mzk.kramerius.fedoraaccess.exception.DatastreamNotFoundException;
import cz.mzk.kramerius.fedoraaccess.rest.RESTConnector;
import cz.mzk.kramerius.k4audiopoc.AudioFormat;
import cz.mzk.kramerius.k4audiopoc.AudioStreamId;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;

/**
 *
 * @author Martin Řehánek <Martin.Rehanek at mzk.cz>
 */
public class CachingFedoraUrlManager implements RepositoryUrlManager {

    //private static final String FEDORA_CONFIG = "fedora.properties";
    private static final String FEDORA_CONFIG = "/home/rehan/NetBeansProjects/K4AudioPOC/src/main/resources/fedora.properties";
    private static final Logger LOGGER = Logger.getLogger(CachingFedoraUrlManager.class.getName());
    //TODO: poresit, aby byl k dispozici singleton RepositoryLinkCache
    private static final RepositoryUrlCache linkCache = new EhcacheUrlCache();
    //TODO: nacitat z souboru na path
    private static FedoraConnector fedoraCon;
    private final boolean urlCaching;

    public CachingFedoraUrlManager(boolean urlCaching) throws IOException {
        this.urlCaching = urlCaching;
        LOGGER.log(Level.INFO, "initializing Fedora connector, url caching: {0}", urlCaching);
        // fedoraCon = new RESTConnector(new FedoraServer(new File(FEDORA_CONFIG)));
    }

    private static FedoraConnector getFedoraConnector() throws IOException {
        if (fedoraCon == null) {
            fedoraCon = new RESTConnector(new FedoraServer(new File(FEDORA_CONFIG)));
        }
        return fedoraCon;
    }

    @Override
    public URL getAudiostreamRepositoryUrl(AudioStreamId id) throws IOException {
        return urlCaching ? getUrlFromCacheOrFedora(id) : getUrlFromFedora(id);
    }

    private URL getUrlFromCacheOrFedora(AudioStreamId id) throws IOException {
        URL urlFromCache = linkCache.getUrl(id);
        if (urlFromCache != null) { //cache hit
            return urlFromCache;
        } else {//cache miss
            URL urlFromFedora = getUrlFromFedora(id);
            linkCache.storeUrl(id, urlFromFedora);
            return urlFromFedora;
        }
    }

    private URL getUrlFromFedora(AudioStreamId id) throws IOException {
        LOGGER.log(Level.FINE, "getting url for {0}", id);
        try {
            Document datastreamXml = getFedoraConnector().getDatastreamAsXml(id.getPid(), versionToDsId(id.getFormat()));
            URL url = urlFromDatastream(datastreamXml);
            LOGGER.log(Level.FINE, "found url {0} for {1}", new Object[]{url, id});
            return url;
        } catch (DatastreamNotFoundException ex) {
            //TODO: error handling
            LOGGER.severe(ex.getMessage());
            return null;
        }
    }

    private DatastreamId versionToDsId(AudioFormat format) {
        return new DatastreamId(format.name());
    }

    private URL urlFromDatastream(Document datastreamXml) throws MalformedURLException {
        XPath xpath = Dom4jUtils.createXPath("//dsProfile:dsLocation");
        Element result = (Element) xpath.selectSingleNode(datastreamXml);
        return new URL(result.getText());
    }

    @Override
    public void close() {
        LOGGER.log(Level.INFO, "destroying {0}", CachingFedoraUrlManager.class.getName());
        if (linkCache != null) {
            linkCache.close();
        }
    }
}
